package main

func main() {
	/*
		1.干净与强迫症：
		（1）编译器不能通过未使用的局部变量（包括未使用的标签）
		（2）“import”未使用的包同样通不过编译
		（3）所有控制结构、函数和方法定义的“{”放到行尾，而不是另起一行
		（4）提供 go fmt 工具格式化代码，使所有的代码风格保持统一

		2.comma, ok 表达式
		（1）获取 map 值。
			获取map中不存在键的值不会发生异常，而是会返回值类型的零值，
				如果想确定map中是否存在 key，则可以使获取 map 值的 comma, ok 语法

		（2）读取 chan 的值。
			读取已经关闭的通道，不会阻塞，也不会引起panic，而是一直返回该通道的零值
				判断通道已关闭的方法：
				A.读取通道的 comma, ok 表达式，若通道关闭，则 ok --> false
				B.通过 range 循环迭代

		（3）类型断言。
			接口断言通常可以使用 comma, ok 语句来确定接口是否绑定某个实例类型，或者判断接口绑定的实例类型是否实现另一个接口

		3.简写模式
			Go语言很多重复的引用或声明可以使用“()”进行简写
			（1）import 包
				eg: import (
						"bufio"
						"bytes"
					)
			（2）多个变量声明
				eg: var (
						bufioReaderPool sync.Pool
						bufioWriter2kPool sync.Pool
						bufioWriter4kPool sync.Pool
					)

		4.多返回值函数
			多返回值函数里如果有 error 或 bool 类型的返回值，则应该将 error 或 bool 作为最后一个返回值

		5.包中函数或方法设计
			很多包的开发者会在内部实现两个“同名”函数或方法，一个首字母大写，用于导出 API 供外部调用；一个首字母小写，用于实现具体逻辑
				一般首字母大写的函数调用首字母小写的函数，同时包装一些功能；
				首字母小写的函数负责更多的底层实现细节

			使用；（大部分情况下不需要）只有在：
				函数逻辑很复杂
				函数在包的内、外部都被调用
			好处：
				减少单个函数的复杂性
				进行调用隔离
	*/
	//comma, ok 表达式

	//1.map
	m := make(map[string]string)

	v, ok := m["some"]

	//通过 ok 进行判断
	if !ok {
		println("m[some] is nil")
	} else {
		println("m[some] =", v)
	}

	//2.chan
	c := make(chan int)

	go func() {
		c <- 1
		c <- 2
		close(c)
	}()

	//A.
	for {
		//使用comma,ok判断通道是否关闭
		v, ok := <-c
		if ok {
			println(v)
		} else {
			break
		}
	}

	//B.使用 range 更加简洁
	for v := range c {
		println(v)
	}

	//3.类型断言
	//判断接口body绑定的实例是否实现了另一个接口io.ReadCloser
	//rc, ok := body.(io.ReadCloser)

	//判断接口Body绑定的实例类型是否是*maxBytesReader具体类型
	//if _, ok := r.Body.(*maxBytesReader); !ok{}
}
